package com.banmao.desktoptools.copyfilesScene.controller;

import com.banmao.commontools.CopyFiles;
import com.banmao.commontools.vo.CopyConfigPojo;
import com.banmao.commontools.vo.R;
import com.banmao.desktoptools.FXMain;
import com.banmao.desktoptools.baseView.Message;
import com.banmao.desktoptools.copyfilesScene.FilePojo;
import com.banmao.desktoptools.util.FileIconUtil;
import com.banmao.desktoptools.util.ResultOutput;
import de.felixroske.jfxsupport.FXMLController;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import javafx.scene.image.ImageView;
import javafx.scene.image.WritableImage;
import javafx.stage.DirectoryChooser;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.StopWatch;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Map;
import java.util.Objects;
import java.util.ResourceBundle;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

@Slf4j
@FXMLController
public class CopyFilesController implements Initializable {

    // 开始复制按钮
    public Button start_button;
    // 源路径
    public TextField source_path_text;
    // 选择源路径
    public Button source_path_button;
    // 输出目录（可选）
    public TextField export_path_text;
    // 选择输出目录
    public Button export_path_button;
    // 前缀
    public TextField prefix_text;
    // 后缀长度
    public TextField suffix_len;
    // 排序方式
    public ChoiceBox<String> order_method;
    // 结果输出
    public TextArea result_output;
    // 文件树
    public TreeView<Object> file_tree;

    @Override
    public void initialize(URL url, ResourceBundle resourceBundle) {
        // 初始化排序方式的下拉框
        ArrayList<String> orderMethodsName = CopyFiles.getOrderMethodsName();
        for (String name : orderMethodsName) {
            order_method.getItems().add(name);
        }
        if(order_method.getItems().size() > 0) {
            String initName = (String) order_method.getItems().get(0);
            order_method.setValue(initName);
        } else {
            // 没有拿到值，弹出提示框
            Message message = new Message("软件错误", "没有获取到排序方式", Alert.AlertType.ERROR);
            message.showAndWait();
        }

        // result_output不可编辑
        result_output.setEditable(false);

    }

    public void startCopy(ActionEvent actionEvent) throws InterruptedException {
        String order_method = (String) this.order_method.getValue();
        CopyConfigPojo copyConfigPojo = new CopyConfigPojo(prefix_text.getText(), suffix_len.getText(),
                source_path_text.getText(), export_path_text.getText(), order_method);

        CompletableFuture.runAsync(() -> {
            final ByteArrayOutputStream bos = new ByteArrayOutputStream();
            CopyFiles.setOutputStream(bos);

            // 异步获取输出流
            ResultOutput resultOutput = new ResultOutput(bos, this.result_output);
            //thread.setDaemon(true);
            resultOutput.start();
            result_output.appendText("==============开始复制==============\n");
            R result = CopyFiles.copyFiles(copyConfigPojo);

            //Map<String, Object> resultMap = CopyFiles.copyFiles(copyConfigPojo);
            Object msg = result.getData();
            result_output.appendText(msg + "\n");

            result_output.appendText("==============复制结束==============\n\n");
            //Thread.sleep(100);
            resultOutput.stopFlag();
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

            log.info("输出流线程存活状态: " + resultOutput.isAlive());
        });


        // 折叠文件列表
        file_tree.getRoot().setExpanded(false);

    }

    // 获取源路径
    public void getSourcePath(ActionEvent actionEvent) {
        DirectoryChooser directoryChooser = new DirectoryChooser();
        directoryChooser.setTitle("选择源路径");
        if(StringUtils.isNotBlank(source_path_text.getText())) {
            directoryChooser.setInitialDirectory(new File(source_path_text.getText()));
        }
        File file = directoryChooser.showDialog(FXMain.getStage());
        if(file != null) {
            String sourcePath = file.getAbsolutePath();
            source_path_text.setText(sourcePath);
            if(StringUtils.isBlank(export_path_text.getText())) {
                export_path_text.setText(sourcePath + "_output");
            }

            // 耗时操作，异步进行
            Platform.runLater(() -> {
                StopWatch stopWatch = new StopWatch();
                stopWatch.start("生成文件树");
                // 获取文件树
                FilePojo filePojo = new FilePojo(new File(sourcePath));

                getCurrentFiles(filePojo);

                generateFilesTress(filePojo);

                stopWatch.stop();
                log.info("{} 生成文件树耗费 {} 秒", sourcePath, stopWatch.getTotalTimeSeconds());
            });

        }

    }

    private static final String TEMP_TREEITEM_VALUE = "__TEMP__";

    private void generateFilesTress(FilePojo filePojo) {
        File file = filePojo.getFile();
        TreeItem<Object> root = new TreeItem<>(StringUtils.isBlank(file.getName()) ?
                file.getAbsolutePath() : file.getName());

        root.addEventHandler(TreeItem.branchExpandedEvent(), event -> {
            TreeItem<Object> treeItem = event.getTreeItem();
            //String fileName = (String) treeItem.getValue();
            if(treeItem.getChildren().size() == 0) {
                return;
            }
            TreeItem<Object> firstItem = treeItem.getChildren().get(0);
            if(TEMP_TREEITEM_VALUE.equals(firstItem.getValue())) {
                StopWatch stopWatch = new StopWatch();
                stopWatch.start(file.getAbsolutePath() + "文件树加载");
                treeItem.getChildren().clear();
                // 懒加载
                // 拼接得到绝对路径
                FilePojo treeItemFiles = new FilePojo(new File(file.getAbsolutePath()));
                getCurrentFiles(treeItemFiles);
                generateFilesTress(treeItemFiles, treeItem);
                stopWatch.stop();
                log.info("{} 生成文件树耗费 {} 秒", file.getAbsolutePath(), stopWatch.getTotalTimeSeconds());
            }
        });

        root.addEventHandler(TreeItem.branchCollapsedEvent(), (event) -> {
            TreeItem<Object> item = event.getTreeItem();
            log.info("清理了treeitem {}", item.getValue());
            item.getChildren().clear();
            item.getChildren().add(new TreeItem<>(TEMP_TREEITEM_VALUE));
        });

        WritableImage fileIcon = FileIconUtil.getFileIcon(file.getAbsolutePath());
        root.setGraphic(new ImageView(fileIcon));

        generateFilesTress(filePojo, root);

        file_tree.setRoot(root);
    }

    private void generateFilesTress(FilePojo filePojo, TreeItem<Object> rootItem) {

        for (FilePojo child : filePojo.getChildren()) {
            if (child == null) continue;
            File file = child.getFile();
            TreeItem<Object> item = new TreeItem<>(file.getName());
            String filePath = file.getAbsolutePath();
            if(file.exists() && file.isDirectory()) {
                TreeItem<Object> tempItem = new TreeItem<>(TEMP_TREEITEM_VALUE);
                item.getChildren().add(tempItem);
                item.addEventHandler(TreeItem.branchExpandedEvent(), event -> {
                    TreeItem<Object> treeItem = event.getTreeItem();
                    //String fileName = (String) treeItem.getValue();
                    if(treeItem.getChildren().size() == 0) {
                        return;
                    }
                    TreeItem<Object> firstItem = treeItem.getChildren().get(0);
                    if(TEMP_TREEITEM_VALUE.equals(firstItem.getValue())) {
                        StopWatch stopWatch = new StopWatch();
                        stopWatch.start(filePath + "文件树加载");
                        treeItem.getChildren().clear();
                        // 懒加载
                        // 拼接得到绝对路径
                        FilePojo treeItemFiles = new FilePojo(new File(filePath));
                        getCurrentFiles(treeItemFiles);
                        generateFilesTress(treeItemFiles, treeItem);
                        stopWatch.stop();
                        log.info("{} 生成文件树耗费 {} 秒", filePath, stopWatch.getTotalTimeSeconds());
                    }

                });

            }
            // 设置图标
            WritableImage fileIcon = FileIconUtil.getFileIcon(filePath);
            item.setGraphic(new ImageView(fileIcon));

            rootItem.getChildren().add(item);
        }
    }


    private void getCurrentFiles(FilePojo root) {
        if(root == null) {
            return;
        }

        File file = root.getFile();
        if(file == null || !file.exists()) {
            return;
        }

        if(file.isDirectory()) {
            // 是目录
            ArrayList<FilePojo> children = root.getChildren();
            if(file.listFiles() == null || Objects.requireNonNull(file.listFiles()).length == 0) {
                children.add(null);
                return;
            }
            for (File listfile : Objects.requireNonNull(file.listFiles())) {
                FilePojo filePojo = new FilePojo(listfile);
                children.add(filePojo);
            }

        }

    }

    public void getExportPath(ActionEvent actionEvent) {
        DirectoryChooser directoryChooser = new DirectoryChooser();
        directoryChooser.setTitle("选择输出路径");
        File file = directoryChooser.showDialog(FXMain.getStage());
        if(file != null) {
            export_path_text.setText(file.getAbsolutePath());
        }
    }


    public void clearResultOutput(ActionEvent actionEvent) {
        // 清空输出信息
        result_output.clear();
    }
}
